package net.kem.android.positioner;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

class Settings {
	private static final Pattern PATTERN = Pattern.compile("(.+):(\\d+)");
	private static SharedPreferences prefs;
//	public static final String PREFS_NAME = "net.kem.android.positioner.Settings";
//	public static final String PREFS_POI_NAME = "net.kem.android.positioner.Settings_POI";
	static String PARAM_HOST_PORT = "host";
	static String PARAM_USERNAME = "username";
	static String PARAM_PASSWORD = "password";
	static String PARAM_HOME_WIFI_ID;
	static String PARAM_WIFI_HOST_PORT;
	static String PARAM_POIS = "prfPOIs";
	static String PARAM_GPSSETTINGS = "GPSSettings";
	static String PARAM_IS_AUTO_GPS_SETTINGS = "GPSAutoRefreshDistance";
	static String PARAM_KEEP_SERVICE_RUNNING = "KeepServiceRunning";
	static String PARAM_GPS_REFRESH_DISTANCE = "GPSRefreshDistance";
	static String PARAM_GPS_REFRESH_INTERVAL = "GPSRefreshInterval";
	static String PARAM_POI_RADIUS = "PoiRadius";
	static String PARAM_GPS_ACCURACY_THRESHOLD = "GPSAccuracyThreshold";
//
//	public static final String PARAM_IS_SERVICE_RUNNING = "IsServiceRunning";
//
	public static final int GPS_REFRESH_DISTANCE_DEFAULT = 100;
	public static final int GPS_REFRESH_INTERVAL_DEFAULT = 120;
	public static final int GPS_ACCURACY_THRESHOLD_DEFAULT = 10;
	public static final int POI_RADIUS_DEFAULT = 100;
	private static String host;
	private static int port;
	private static String username;
	private static String password;
	private static String homeWifiId;	// Some id (e.g. SSID) that identifies a WiFi connection.
	private static String wifiHost;	// Host name (IP address) of server that will be connected via WiFi.
	private static int wifiPort;	// Port of server that will be connected via WiFi.
	private static boolean gpsAutoRefreshDistance;
//	private static int gpsRefreshInterval;
//	private static int gpsRefreshDistance;
//	private static int poiRadius;
//	private static int gpsAccuracyThreshold;
	private static final Set<POI> POIS = new TreeSet<POI>();

	static void init(Context activity) {
		if(prefs == null) {
//			prefs = activity.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
			// Get the xml/preferences.xml preferences
	     	prefs = PreferenceManager.getDefaultSharedPreferences(activity);

	     	PARAM_HOST_PORT = activity.getResources().getString(R.string.prfServerHostPort);
	     	PARAM_USERNAME = activity.getResources().getString(R.string.prfUsername);
	     	PARAM_PASSWORD = activity.getResources().getString(R.string.prfPassword);

	     	PARAM_HOME_WIFI_ID = activity.getResources().getString(R.string.prfHomeWiFiId);
	     	PARAM_WIFI_HOST_PORT = activity.getResources().getString(R.string.prfWiFiServerHostPort);

	     	PARAM_POIS = activity.getResources().getString(R.string.prfPOIs);
	     	PARAM_KEEP_SERVICE_RUNNING = activity.getResources().getString(R.string.prfToggleServiceRunning);

	     	PARAM_GPSSETTINGS = activity.getResources().getString(R.string.prfGPSSettings);
	     	PARAM_IS_AUTO_GPS_SETTINGS = activity.getResources().getString(R.string.prfToggleGPSAutoSettings);
	     	PARAM_GPS_REFRESH_DISTANCE = activity.getResources().getString(R.string.prfGPSRefreshDistance);
	     	PARAM_GPS_REFRESH_INTERVAL = activity.getResources().getString(R.string.prfGPSRefreshInterval);
	     	PARAM_POI_RADIUS = activity.getResources().getString(R.string.prfPOIRadius);
	     	PARAM_GPS_ACCURACY_THRESHOLD = activity.getResources().getString(R.string.prfGPSAccuracyThreshold);


			if(getHost() == null) {
				setHostPort("znetwork.no-ip.org:80");
			}
			if(getHomeWiFiId().length() == 0) {
				setHomeWiFiId("HomeRouter");
			}
			if(getWiFiHost() == null) {
				setWiFiHostPort("10.0.0.2:80");
			}
			if(getUsername().length() == 0) {
				setUsername("0507362270");
				setGPSAutoRefreshDistance(true);
			}
			if(getPassword().length() == 0) {
				setPassword("p1r0zH0k@tEnE");
			}
			boolean onePOIfound = false;
			for(Map.Entry<String, ?> me: prefs.getAll().entrySet()) {
				if(me.getKey().startsWith("POI_")) {
					String poiKey = me.getKey();
					POI poi = POI.load(poiKey);
					POIS.add(poi);
					onePOIfound = true;
				}
			}
			if(!onePOIfound) {
				/*POIS.add(new POI(1, "Home").store());
				POIS.add(new POI(2, "Work").store());
				POIS.add(new POI(3, "Supermartket").store()); //Club
				POIS.add(new POI(4, "Bank").store()); //Gym
				POIS.add(new POI(5, "Friends").store()); //Pub
*/			}
		}
	}

	static boolean removeValue(String key) {
		SharedPreferences.Editor editor = prefs.edit();
		editor.remove(key);
		boolean res = editor.commit();
		return res;
	}
	static String getValue(String key) {
		String res = prefs.getString(key, "");
		return res;
	}
	static void setValue(String key, String value) {
		SharedPreferences.Editor editor = prefs.edit();
		editor.putString(key, value);
		editor.commit();
	}

	static Boolean getValueBoolean(String key) {
		Boolean res = prefs.getBoolean(key, false);
		return res;
	}
	static void setValue(String key, Boolean value) {
		SharedPreferences.Editor editor = prefs.edit();
		editor.putBoolean(key, value);
		editor.commit();
	}

	static Float getValueFloat(String key) {
		Float res = prefs.getFloat(key, -1.0f);
		return res;
	}
	static void setValue(String key, Float value) {
		SharedPreferences.Editor editor = prefs.edit();
		editor.putFloat(key, value);
		editor.commit();
	}

	static Integer getValueInt(String key, int defValue) {
		Integer res = prefs.getInt(key, defValue);
		return res;
	}
	static void setValue(String key, Integer value) {
		SharedPreferences.Editor editor = prefs.edit();
		editor.putInt(key, value);
		editor.commit();
	}


	static String getHost() {
		if(host == null || host.length() == 0) {
			getHostPort();
		}
		return host;
	}
	static int getPort() {
		if(port == 0) {
			getHostPort();
		}
		return port;
	}

	private static void getHostPort() {
		if(host == null || host.length() == 0) {
			// "znetwork.no-ip.org:80"
			String hst = prefs.getString(PARAM_HOST_PORT, "");
			Matcher m = PATTERN.matcher(hst);
			if(m.matches()) {
				host = m.group(1);
				port = Integer.parseInt(m.group(2));
			}
		}
	}

	static void setHostPort(String hostPort) {
		Matcher m = PATTERN.matcher(hostPort);
		if(m.matches()) {
			host = m.group(1);
			port = Integer.parseInt(m.group(2));
			SharedPreferences.Editor editor = prefs.edit();
			editor.putString(PARAM_HOST_PORT, hostPort);
			editor.commit();
		}
	}


	static String getUsername() {
		if(username == null || username.length() == 0) {
			username = prefs.getString(PARAM_USERNAME, "");
		}
		return username;
	}
	static void setUsername(String username) {
		Settings.username = username;
		SharedPreferences.Editor editor = prefs.edit();
		editor.putString(PARAM_USERNAME, username);
		editor.commit();
	}

	static String getPassword() {
		if(password == null || password.length() == 0) {
			password = prefs.getString(PARAM_PASSWORD, "");
		}
		return password;
	}
	static void setPassword(String password) {
		Settings.password = password;
		SharedPreferences.Editor editor = prefs.edit();
		editor.putString(PARAM_PASSWORD, password);
		editor.commit();
	}

	static String getHomeWiFiId() {
		if(homeWifiId == null || homeWifiId.length() == 0) {
			homeWifiId = prefs.getString(PARAM_HOME_WIFI_ID, "");
		}
		return homeWifiId;
	}
	static void setHomeWiFiId(String homeWifiId) {
		Settings.homeWifiId = homeWifiId;
		SharedPreferences.Editor editor = prefs.edit();
		editor.putString(PARAM_HOME_WIFI_ID, homeWifiId);
		editor.commit();
	}

	static String getWiFiHost() {
		if(wifiHost == null || wifiHost.length() == 0) {
			getWiFiHostPort();
		}
		return wifiHost;
	}
	static int getWiFiPort() {
		if(wifiPort == 0) {
			getWiFiHostPort();
		}
		return wifiPort;
	}

	private static void getWiFiHostPort() {
		if(wifiHost == null || wifiHost.length() == 0) {
			// "znetwork.no-ip.org:80"
			String hst = prefs.getString(PARAM_WIFI_HOST_PORT, "");
			Matcher m = PATTERN.matcher(hst);
			if(m.matches()) {
				wifiHost = m.group(1);
				wifiPort = Integer.parseInt(m.group(2));
			}
		}
	}

	static void setWiFiHostPort(String wifiHostPort) {
		Matcher m = PATTERN.matcher(wifiHostPort);
		if(m.matches()) {
			wifiHost = m.group(1);
			wifiPort = Integer.parseInt(m.group(2));
			SharedPreferences.Editor editor = prefs.edit();
			editor.putString(PARAM_WIFI_HOST_PORT, wifiHostPort);
			editor.commit();
		}
	}

	static int getGPSRefreshDistance() {
		int gpsRefreshDistance = getValueInt(PARAM_GPS_REFRESH_DISTANCE, GPS_REFRESH_DISTANCE_DEFAULT);
		return gpsRefreshDistance;
	}
	static void setGPSRefreshDistance(int gpsRefreshDistance) {
		setValue(PARAM_GPS_REFRESH_DISTANCE, gpsRefreshDistance);
	}

	static boolean getGPSAutoRefreshDistance() {
		gpsAutoRefreshDistance = getValueBoolean(PARAM_IS_AUTO_GPS_SETTINGS);
		return gpsAutoRefreshDistance;
	}
	static void setGPSAutoRefreshDistance(boolean gpsAutoRefreshDistance) {
		Settings.gpsAutoRefreshDistance = gpsAutoRefreshDistance;
		setValue(PARAM_IS_AUTO_GPS_SETTINGS, gpsAutoRefreshDistance);
	}

	static int getGPSRefreshInterval() {
		int gpsRefreshInterval = getValueInt(PARAM_GPS_REFRESH_INTERVAL, 180);
		return gpsRefreshInterval;
	}
	static void setGPSRefreshInterval(int gpsRefreshInterval) {
		setValue(PARAM_GPS_REFRESH_INTERVAL, gpsRefreshInterval);
	}


	// POI Begin
	@SuppressWarnings("unchecked")
	static Set<POI> getPOIs() {
		return (Set<POI>)((TreeSet<POI>)POIS).clone();
	}

	static POI deletePOI(POI poi) {
		POI res = null;
		synchronized(POIS) {
			if(POIS.remove(poi)) {
				res = poi;
				removeValue("POI_" + poi.getId());
			}
		}
		return res;
	}

	static void storePOI(POI poi) {
		synchronized(POIS) {
			if(POIS.add(poi)) {
				setValue("POI_" + poi.getId(), poi.getPOIdata());
			}
		}
	}

	static void storePOIs(List<POI> pois) {
		synchronized(POIS) {
			POIS.clear();
			for(POI poi: pois) {
				POIS.add(poi);
				setValue("POI_" + poi.getId(), poi.getPOIdata());
			}
		}
	}

	static boolean isPOIDefined(String poiName) {
		boolean res;
		POI poi = getPOIByName(poiName);
		if(poi != null) {
			res = poi.isDefined();
		} else {
			res = false;
		}
		return res;
	}

	static POI getPOIByName(String poiName) {
		for(POI poi: POIS) {
			if(poi.getName().equals(poiName)) {
				return poi;
			}
		}
		return null;
	}

	static POI getPOIById(int poiId) {
		for(POI poi: POIS) {
			if(poi.getId() == poiId) {
				return poi;
			}
		}
		return null;
	}

	/*static POI getByResourceId(int rId) {
		POI res;
		switch(rId) {
			case R.id.contextMenuHome:
				res = getPOIByName("Home");
				break;
			case R.id.contextMenuWork:
				res = getPOIByName("Work");
				break;
			case R.id.contextMenuSupermartket:
				res = getPOIByName("Supermartket");
				break;
			case R.id.contextMenuBank:
				res = getPOIByName("Bank");
				break;
			case R.id.contextMenuFriends:
				res = getPOIByName("Friends");
				break;
			default: res = null;
		}
		return res;
	}*/
	// POI End

	static int getPOIRadius() {
		int poiRadius = getValueInt(PARAM_POI_RADIUS, 100);
		return poiRadius;
	}

	static void setPOIRadius(int poiRadius) {
		setValue(PARAM_POI_RADIUS, poiRadius);
	}

	static int getGPSAccuracyThreshold() {
		int gpsAccuracyThreshold = getValueInt(PARAM_GPS_ACCURACY_THRESHOLD, 5);
		return gpsAccuracyThreshold;
	}

	static void setGPSAccuracyThreshold(int gpsAccuracyThreshold) {
		setValue(PARAM_GPS_ACCURACY_THRESHOLD, gpsAccuracyThreshold);
	}
}